/*  Test Menezes-Qu-Vanstone code for polynomial basis  */

#include <stdio.h>
#include "bigint.h"
#include "poly.h"
#include "eliptic.h"
#include "protocols.h"

extern FIELD2N poly_prime;
extern void sha_memory();
extern unsigned long random_seed;

main()
{
	EC_PARAMETER	Base;
	EC_KEYPAIR		side1_perm, side2_perm;
	EC_KEYPAIR		side1_ephem, side2_ephem;
	BIGINT			prime_order;
	POINT			temp;
	FIELD2N			side1_secret, side2_secret;
	FIELD2N			roots[3];
	INDEX			error;
	
/*	char string1[MAXSTRING] = "324518553658426701487448656461467"; /*N 109 */ 
	char string1[MAXSTRING] = "324518553658426723114957572335741"; /*N 111  */
/*	char string1[MAXSTRING] = "5192296858534827627896703833467507"; /*N 113  */
/*	char string1[MAXSTRING] = "680564733841876926932320129493409985129";*/ /*N~ 131 */
/*	char string1[MAXSTRING] = "5444517870735015415344659586094410599059"; /*N 134 (g^2 = g+1)	*/
/*	char string1[MAXSTRING] = "19822884620916109459140767798279811163792081";*/ /*N~ 148 GF(16) */
/*	char string1[MAXSTRING] = "91343852333181432387730573045979447452365303319";*/  /* N 158 */
/*	char string1[MAXSTRING] = "5846006549323611672814741753598448348329118574063"; */ /* 163 */ 

	random_seed = 0xBEEFACED;

	if (!irreducible(&poly_prime)) return(0);
	print_field("poly_prime = ", &poly_prime);
	
	if (error = init_poly_math())
	{
		printf("Can't initialize S matrix, row = %d\n", error);
		return(-1);
	}

/*  compute curve order from Koblitz data  */

	ascii_to_bigint(&string1, &prime_order);
	int_to_field( &prime_order, &Base.pnt_order);
	null( &Base.cofactor);
	Base.cofactor.e[NUMWORD] = 8;

	printf("create Base curve and point\n\n");

	Base.crv.form = 0;
	null(&Base.crv.a2);
	poly_gf8(&poly_prime, roots);
	copy( &roots[1], &Base.crv.a6);
	print_curve("Public curve", &Base.crv);
	
	rand_point(&temp, &Base.crv);
	poly_elptic_mul(&Base.cofactor, &temp, &Base.pnt, &Base.crv);
	print_point("Base point", &Base.pnt);

	
/*  Create each sides public keys.  These are the permenent
	versions which can be saved in a data base.
*/

	printf("permenent keys\n");
	poly_ECKGP( &Base, &side1_perm);
	print_field("side 1 secret key", &side1_perm.prvt_key);
	print_point("side 1 public key", &side1_perm.pblc_key);
	poly_ECKGP( &Base, &side2_perm);
	print_field("side 2 secret key", &side2_perm.prvt_key);
	print_point("side 2 public key", &side2_perm.pblc_key);

/*  Create each sides ephemeral keys.  These are destroyed
	after each link is established.
*/

	printf("ephemeral keys\n");
	poly_ECKGP( &Base, &side1_ephem);
	print_field("side 1 secret key", &side1_ephem.prvt_key);
	print_point("side 1 public key", &side1_ephem.pblc_key);
	poly_ECKGP( &Base, &side2_ephem);
	print_field("side 2 secret key", &side2_ephem.prvt_key);
	print_point("side 2 public key", &side2_ephem.pblc_key);

/*  Each side exchanges both sets of public keys.  Then they
	both perform the same calculations with the other sides
	data to find the same shared secret.
*/

	poly_mqv( &Base, &side1_perm, &side1_ephem, &side2_perm.pblc_key,
				&side2_ephem.pblc_key, &side1_secret);
	print_field("side 1 secret value", &side1_secret);
	poly_mqv( &Base, &side2_perm, &side2_ephem, &side1_perm.pblc_key,
				&side1_ephem.pblc_key, &side2_secret);
	print_field("side 2 secret value", &side2_secret);
}
